package link.luyu.plugin.brochain.web3.methods.request;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigInteger;
import org.web3j.utils.Numeric;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Transaction {

    @JsonProperty("regionid")
    private String regionId;

    private String to;
    private String data;
    private BigInteger nonce;

    @JsonProperty("blocklimit")
    private BigInteger blockLimit;

    private BigInteger r;
    private BigInteger s;
    private long v;

    public Transaction(
            String regionId,
            String to,
            String data,
            BigInteger nonce,
            BigInteger blockLimit,
            BigInteger r,
            BigInteger s,
            long v) {
        this.regionId = regionId;
        this.to = to;

        if (data != null) {
            this.data = Numeric.prependHexPrefix(data);
        }

        this.nonce = nonce;
        this.blockLimit = blockLimit;
        this.r = r;
        this.s = s;
        this.v = v;
    }

    public static Transaction createContractTransaction(
            String regionId,
            String init,
            BigInteger nonce,
            BigInteger blockLimit,
            BigInteger r,
            BigInteger s,
            long v) {

        return new Transaction(regionId, null, init, nonce, blockLimit, r, s, v);
    }

    public static Transaction createFunctionCallTransaction(
            String regionId,
            String to,
            String data,
            BigInteger nonce,
            BigInteger blockLimit,
            BigInteger r,
            BigInteger s,
            long v) {

        return new Transaction(regionId, to, data, nonce, blockLimit, r, s, v);
    }

    public String getRegionId() {
        return regionId;
    }

    public String getTo() {
        return to;
    }

    public String getData() {
        return data;
    }

    public String getNonce() {
        return convert(nonce);
    }

    public String getBlockLimit() {
        return convert(blockLimit);
    }

    public String getR() {
        return convert(r);
    }

    public String getS() {
        return convert(s);
    }

    public String getV() {
        return convert(v);
    }

    private static String convert(BigInteger value) {
        if (value != null) {
            return Numeric.encodeQuantity(value);
        } else {
            return null; // we don't want the field to be encoded if not present
        }
    }

    private static String convert(long v) {
        return Numeric.encodeQuantity(BigInteger.valueOf(v));
    }
}
